
package com.hlkj.pay.app.order.impl;
/*
 * Hlpay-Plus aggregate payment system.
 * Copyright (c) 2024-2025 Hlpay Team Copyright has the right of final interpretation.
 */

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import com.hlkj.framework.common.pojo.CommonResult;
import com.hlkj.framework.common.pojo.LocalContext;
import com.hlkj.framework.common.pojo.PageResult;
import com.hlkj.framework.common.util.collection.CollectionUtils;
import com.hlkj.framework.common.util.json.JsonUtils;
import com.hlkj.pay.common.OpenApiResultCode;
import com.hlkj.pay.common.PayResultCode;
import com.hlkj.pay.dto.LocalMerchantRequest;
import com.hlkj.pay.dto.merchant.MerchantAppQueryDto;
import com.hlkj.pay.dto.merchant.RouterConfigDto;
import com.hlkj.pay.dto.merchant.RouterResultDto;
import com.hlkj.pay.dto.merchant.access.MerchantAccessAuthQueryDto;
import com.hlkj.pay.dto.order.PayOrderQueryDto;
import com.hlkj.pay.dto.order.RouterOrderDataDto;
import com.hlkj.pay.dto.order.RouterOrderMessageDto;
import com.hlkj.pay.enums.CommonEnum;
import com.hlkj.pay.enums.MerchantEnum;
import com.hlkj.pay.enums.PayEnums;
import com.hlkj.pay.enums.PayOrderEnums;
import com.hlkj.pay.infrastructure.model.common.LimitRouterLogDO;
import com.hlkj.pay.infrastructure.model.merchant.MerchantAccessAuthDO;
import com.hlkj.pay.infrastructure.model.merchant.MerchantAppChannelDO;
import com.hlkj.pay.infrastructure.model.merchant.MerchantAppDO;
import com.hlkj.pay.infrastructure.model.order.PayOrderDO;
import com.hlkj.pay.infrastructure.model.pay.PayWayDO;
import com.hlkj.pay.service.common.IBusinessLogService;
import com.hlkj.pay.service.merchant.IMerchantAccessAuthService;
import com.hlkj.pay.service.merchant.IMerchantApplicationService;
import com.hlkj.pay.service.order.IPayOrderService;
import com.hlkj.pay.util.DateUtils;
import com.hlkj.pay.util.MerchantAppChannelRouterUtil;
import com.hlkj.pay.util.MerchantUtils;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * @author HlpayTeam
 * @date 2024/10/10 9:07
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class MerchantChannelRouteHandler {

    private final IMerchantApplicationService merchantApplicationService;

    private final IMerchantAccessAuthService merchantAccessAuthService;

    private final IPayOrderService payOrderService;

    private final IBusinessLogService businessLogService;

    /**
     * 商户通道路由
     * 
     * @param providerCode
     *            指定服务商
     * @param channelCode
     *            指定的通道
     * @param subChannelCode
     *            指定的子通道id
     * @return
     */
    public CommonResult<RouterResultDto> merchantChannelRoute(String providerCode, String channelCode, String subChannelCode, BigDecimal orderAmount, PayWayDO payWay) {
        String payWayCode = payWay.getCode();
        Integer routerStrategy = 0;
        LocalMerchantRequest localMerchantRequest = (LocalMerchantRequest) LocalContext.get();
        MerchantAppDO merchantAppDO = localMerchantRequest.getMerchantAppDO();
        MerchantAppChannelDO merchantAppSubChannelDO = null;
        if (StringUtils.hasText(subChannelCode)) {
            merchantAppSubChannelDO = merchantApplicationService.queryAppChannelDetail(subChannelCode);
            if (merchantAppSubChannelDO == null) {
                return CommonResult.error(OpenApiResultCode.MERCHANT_APP_CHANNEL_NOT_EXIST);
            }
            //指定具体通道code时 不做开启状态校验
//            if (CommonEnum.YES_NO_TYPE.NO.getCode().equals(merchantAppSubChannelDO.getStatus())) {
//                return CommonResult.error(OpenApiResultCode.MERCHANT_APP_CHANNEL_NOT_EFFECT);
//            }
            if (!merchantAppSubChannelDO.getPayWayCodes().contains(payWayCode)) {
                log.info("merchantChannelRoute 支付方式 payWayCode:{},不存在", payWayCode);
                return CommonResult.error(PayResultCode.PAY_WAY_NOT_EFFECT);
            }
        }
        else {
            // 是否存在默认的通道配置
            RouterConfigDto routerConfigDto = merchantAppDO.getRouterConfigDto();
            String defaultChannel = null;
            if (routerConfigDto != null) {
                if (CommonEnum.YES_NO_TYPE.NO.getCode().equals(routerConfigDto.getRouterStrategy())) {
                    if (!CollectionUtils.isEmpty(routerConfigDto.getOrderAmounts())) {
                        for (RouterConfigDto.RouterConfigOrderAmount routerConfigOrderAmount : routerConfigDto.getOrderAmounts()) {
                            if (routerConfigOrderAmount.getMinOrderAmount() != null && routerConfigOrderAmount.getMaxOrderAmount() != null) {
                                boolean isBetween = orderAmount.compareTo(routerConfigOrderAmount.getMinOrderAmount()) >= 0
                                        && orderAmount.compareTo(routerConfigOrderAmount.getMaxOrderAmount()) <= 0;
                                if (isBetween) {
                                    defaultChannel = routerConfigOrderAmount.getMchChannelCode();
                                    break;
                                }
                            }
                        }
                    }
                }
                routerStrategy = routerConfigDto.getRouterStrategy();
            }
            if (StringUtils.hasText(defaultChannel)) {
                merchantAppSubChannelDO = merchantApplicationService.queryAppChannelDetail(defaultChannel);
                if (merchantAppSubChannelDO != null) {
                    if (CommonEnum.YES_NO_TYPE.NO.getCode().equals(merchantAppSubChannelDO.getStatus()) || !merchantAppSubChannelDO.getPayWayCodes().contains(payWayCode)) {
                        log.info("配置了默认通道,通道参数匹配错误,继续参与后续路由 defaultChannel :{}", defaultChannel);
                        merchantAppSubChannelDO = null;
                    }
                }
            }
            if (merchantAppSubChannelDO == null) {
                List<MerchantAppChannelDO> merchantAppChannelList = merchantApplicationService.queryChannelInfoList(merchantAppDO.getSn(), merchantAppDO.getAppId(), providerCode,
                        channelCode, CommonEnum.YES_NO_TYPE.YES.getCode(),null);
                if (CollectionUtils.isEmpty(merchantAppChannelList)) {
                    return CommonResult.error(OpenApiResultCode.MERCHANT_APP_CHANNEL_NOT_EXIST);
                }
                merchantAppChannelList = merchantAppChannelList.stream().filter(merchantAppChannelDO -> merchantAppChannelDO.getPayWayCodes().contains(payWayCode))
                        .collect(Collectors.toList());
                if (CollectionUtils.isEmpty(merchantAppChannelList)) {
                    log.info("merchantChannelRoute 支付方式 payWayCode:{},不存在", payWayCode);
                    return CommonResult.error(OpenApiResultCode.PAY_WAY_NOT_EFFECT);
                }

                // 商户轮询配置
                MerchantEnum.ROUTE_TYPE routeType = MerchantEnum.ROUTE_TYPE.from(routerStrategy);
                switch (routeType){
                    case DEFAULT:
                        break;
                    case RANDOM_MULTIPLE:
                        merchantAppChannelList = merchantApplicationService.queryChannelInfoList(merchantAppDO.getSn(), merchantAppDO.getAppId(), providerCode,
                                channelCode, CommonEnum.YES_NO_TYPE.YES.getCode(),null);
                        if (CollectionUtils.isEmpty(merchantAppChannelList)) {
                            return CommonResult.error(0,"商户轮询配置随机多个 APP轮询通道不存在 channelCode:"+channelCode);
                        }
                        merchantAppChannelList = merchantAppChannelList.stream().filter(merchantAppChannelDO -> merchantAppChannelDO.getPayWayCodes().contains(payWayCode))
                                .collect(Collectors.toList());
                        if (CollectionUtils.isEmpty(merchantAppChannelList)) {
                            log.info("merchantChannelRoute 支付方式 payWayCode:{},不存在", payWayCode);
                            return CommonResult.error(OpenApiResultCode.PAY_WAY_NOT_EFFECT);
                        }
                        break;
                    case SEQ_SINGLE:
                        // 查询所有开启的通道
                        List<MerchantAppChannelDO> merchantAppSeqChannelList = merchantApplicationService.queryChannelInfoList(merchantAppDO.getSn(), merchantAppDO.getAppId(), providerCode,
                                channelCode, CommonEnum.YES_NO_TYPE.YES.getCode(),null);
                        if(CollUtil.isEmpty(merchantAppSeqChannelList)){
                            return CommonResult.error(OpenApiResultCode.MERCHANT_APP_CHANNEL_NOT_EXIST);
                        }
                        // 支付方式校验
                        merchantAppSeqChannelList = merchantAppSeqChannelList.stream().filter(merchantAppChannelDO -> merchantAppChannelDO.getPayWayCodes().contains(payWayCode))
                                .collect(Collectors.toList());
                        if (CollectionUtils.isEmpty(merchantAppChannelList)) {
                            log.info("merchantChannelRoute 支付方式 payWayCode:{},不存在", payWayCode);
                            return CommonResult.error(OpenApiResultCode.PAY_WAY_NOT_EFFECT);
                        }
                        if(merchantAppSeqChannelList.size() > 1){
                            return CommonResult.error(0,"商户轮询配置顺序单个只允许一个开启的通道 channelCode:"+channelCode);
                        }
                        break;
                }
                merchantAppSubChannelDO = MerchantAppChannelRouterUtil.router(merchantAppChannelList);
                if(merchantAppChannelList.size() > 1){
                    log.info("本次轮询渠道权重 weight:{},data:{]",merchantAppSubChannelDO.getWeight(), JSONUtil.toJsonStr(merchantAppSubChannelDO));
                }
            }
        }
        localMerchantRequest.setProviderCode(merchantAppSubChannelDO.getProviderCode());
        localMerchantRequest.setChannelCode(merchantAppSubChannelDO.getChannelCode());
        localMerchantRequest.setMchChannelCode(merchantAppSubChannelDO.getCode());
        LocalContext.set(localMerchantRequest);
        RouterResultDto routerResultDto = new RouterResultDto();
        routerResultDto.setMerchantAppChannel(merchantAppSubChannelDO);
        if (merchantAppSubChannelDO != null && merchantAppSubChannelDO.getAccessId() != null) {
            Integer type = payWay.getType();
            // 子通道路由
            if (PayEnums.PAY_TYPE.WECHAT.getCode().equals(type) || PayEnums.PAY_TYPE.ALIPAY.getCode().equals(type)) {
                PayEnums.PAY_TYPE payType = PayEnums.PAY_TYPE.fromByCode(type);
                MerchantAccessAuthDO merchantAccessAuthDO = null;
                // 查询所有开启的AT通道
                List<MerchantAccessAuthDO> merchantAccessAuthList = null;
                // 商户轮询配置
                MerchantEnum.ROUTE_TYPE routeType = MerchantEnum.ROUTE_TYPE.from(routerStrategy);
                switch (routeType){
                    case DEFAULT:
                        break;
                    case RANDOM_MULTIPLE:
                        // 查询所有开启的AT通道
                        merchantAccessAuthList = merchantAccessAuthService.routerAccessAuthList(merchantAppSubChannelDO.getAccessId(), payType,1,null);
                        if(CollUtil.isEmpty(merchantAccessAuthList)){
                            return CommonResult.error(0,"商户轮询配置随机多个AT通道不存在 subMchId:"+merchantAppSubChannelDO.getSubMchId());
                        }
                        // 根据权重随机一个
                        merchantAccessAuthDO = MerchantAppChannelRouterUtil.routerAt(merchantAccessAuthList);
                        break;
                    case SEQ_SINGLE:
                        // 查询所有开启的AT通道
                        merchantAccessAuthList = merchantAccessAuthService.routerAccessAuthList(merchantAppSubChannelDO.getAccessId(), payType,1,null);
                        if(CollUtil.isEmpty(merchantAccessAuthList)){
                            return CommonResult.error(0,"商户轮询配置顺序单个AT通道不存在 subMchId:"+merchantAppSubChannelDO.getSubMchId());
                        }else{
                            if(merchantAccessAuthList.size() > 1){
                                return CommonResult.error(0,"商户轮询配置顺序单个只允许一个开启的AT通道 subMchId:"+merchantAppSubChannelDO.getSubMchId());
                            }
                        }
                        merchantAccessAuthDO = merchantAccessAuthList.get(0);
                        break;
                }

                if (merchantAccessAuthDO != null) {
                    routerResultDto.setMerchantAccessAuth(merchantAccessAuthDO);
                }
            }
        }
        return CommonResult.success(routerResultDto);
    }



    public CommonResult<Void> merchantChannelRouteFail(PayOrderDO payOrderDO,PayWayDO payWayDO,MerchantAccessAuthDO merchantAccessAuthNow) {
        String payWayCode = payWayDO.getCode();
        LocalMerchantRequest localMerchantRequest = (LocalMerchantRequest) LocalContext.get();
        MerchantAppDO merchantAppDO = localMerchantRequest.getMerchantAppDO();
        MerchantAppChannelDO merchantAppSubChannelDO = null;
        String mchChannelCode = payOrderDO.getMchChannelCode();
        if (StringUtils.hasText(mchChannelCode)) {
            merchantAppSubChannelDO = merchantApplicationService.queryAppChannelDetail(mchChannelCode);
            if (merchantAppSubChannelDO == null) {
                return CommonResult.error(OpenApiResultCode.MERCHANT_APP_CHANNEL_NOT_EXIST);
            }
            if (!merchantAppSubChannelDO.getPayWayCodes().contains(payWayCode)) {
                log.info("merchantChannelRoute 支付方式 payWayCode:{},不存在", payWayCode);
                return CommonResult.error(PayResultCode.PAY_WAY_NOT_EFFECT);
            }

            CommonResult<MerchantAppChannelDO> commonResult = null;
            MerchantAccessAuthDO merchantAccessAuthDO = null;
            // 通道路由配置
            RouterConfigDto routerConfigDto = merchantAppDO.getRouterConfigDto();
            // 轮询策略 0：系统默认 1 顺序单个 2 随机多个
            if(routerConfigDto == null || routerConfigDto.getRouterStrategy() == 0){
                return CommonResult.success();
            }
            // 轮询策略 0：系统默认 1 顺序单个 2 随机多个
            Integer routerStrategy = routerConfigDto.getRouterStrategy();
            // 轮询方式 0:机构通道轮询 1:AT通道轮询
            Integer routerType = routerConfigDto.getRouterType();
            // 轮询方式 0:机构通道轮询 1:AT通道轮询
            Integer routerOrder = routerConfigDto.getRouterOrder();
            // 交易失败是否自动切换或关闭 1:是 0:否
            Integer autoDealFailedNext = routerConfigDto.getAutoDealFailedNext();

            MerchantEnum.ROUTE_TYPE routeType = MerchantEnum.ROUTE_TYPE.from(routerStrategy);
            switch (routeType){
                case DEFAULT:
                    break;
                case SEQ_SINGLE:
                    log.info("merchantChannelRoute getSeqChannel go");
                    if(routerOrder == null){
                        routerOrder = 0;
                    }
                    // 机构通道轮询
                    if(routerType == null ||  routerType == 0){
                        log.info("merchantChannelRoute getSeqChannel APP通道 go");
                        // 是否自动切换下一个
                        if(autoDealFailedNext != null && autoDealFailedNext == 1){
                            // 获取开启通道集合
                            List<MerchantAppChannelDO> merchantAppChannelList = merchantApplicationService.queryChannelInfoList(merchantAppDO.getSn(), merchantAppDO.getAppId(), payOrderDO.getProviderCode(),
                                    payOrderDO.getChannelCode(), 1, null);
                            if (CollectionUtils.isEmpty(merchantAppChannelList)) {
                                return CommonResult.error(OpenApiResultCode.MERCHANT_APP_CHANNEL_NOT_EXIST);
                            }
                            // 支付方式校验
                            merchantAppChannelList = merchantAppChannelList.stream().filter(merchantAppChannelDO -> merchantAppChannelDO.getPayWayCodes().contains(payWayCode))
                                 .collect(Collectors.toList());
                            if (CollectionUtils.isEmpty(merchantAppChannelList)) {
                                log.info("merchantChannelRoute getSeqChannel 支付方式 payWayCode:{},不存在", payWayCode);
                                return CommonResult.error(OpenApiResultCode.PAY_WAY_NOT_EFFECT);
                            }

                            if(merchantAppChannelList.size() > 1){
                                log.info("merchantChannelRoute getSeqChannel APP通道 商户轮询配置顺序单个只允许一个开启的通道");
                                return CommonResult.error(0,"商户轮询配置顺序单个只允许一个开启的通道");
                            }
                            // 查询当前商户下所有通道
                            merchantAppChannelList = merchantApplicationService.queryChannelInfoList(merchantAppDO.getSn(), merchantAppDO.getAppId(), payOrderDO.getProviderCode(),
                                    payOrderDO.getChannelCode(), null,null);
                            commonResult = getSeqChannel(mchChannelCode,localMerchantRequest.getSn(),merchantAppChannelList,payWayCode,routerOrder);
                            if(!commonResult.isSuccess()){
                                log.info("merchantChannelRoute getSeqChannel APP通道 fail:{}",commonResult.getMsg());
                                return CommonResult.error(0,commonResult.getMsg());
                            }
                            // 成功获取下一个通道
                            MerchantAppChannelDO channelNew = commonResult.getData();
                            if(!mchChannelCode.equals(channelNew.getChannelCode())){
                                // 关闭旧通道
                                merchantApplicationService.updateMerchantAppChannelStatus(mchChannelCode,0,payOrderDO.getSn(),payOrderDO.getAppId());
                                // 开启新通道
                                merchantApplicationService.updateMerchantAppChannelStatus(channelNew.getCode(),1,payOrderDO.getSn(),payOrderDO.getAppId());
                                log.info("merchantChannelRoute getSeqChannel APP通道 suceess, close:{} ,open:{}",mchChannelCode,channelNew.getCode());
                            }
                        }
                    }else{
                        // 是否自动切换下一个
                        if(autoDealFailedNext != null &&  autoDealFailedNext == 1){
                            // 查询AT通道
                            List<MerchantAccessAuthDO> merchantAccessAuthList = merchantAccessAuthService.routerAccessAuthList(merchantAppSubChannelDO.getAccessId(), PayEnums.PAY_TYPE.fromByCode(payWayDO.getType()),CommonEnum.YES_NO_TYPE.YES.getCode(),null);
                            if(CollUtil.isEmpty(merchantAccessAuthList)){
                                return CommonResult.error(0,"商户轮询配置顺序单个AT通道不存在");
                            }
                            // 顺序单个只允许一个开启的通道
                            if(merchantAccessAuthList.size() > 1){
                                return CommonResult.error(0,"商户轮询配置顺序单个AT通道只允许一个开启的通道");
                            }
                            // 当前AT通道
                            merchantAccessAuthDO = merchantAccessAuthList.get(0);
                            // 获取开启通道集合
                            List<MerchantAppChannelDO> merchantAppChannelList = merchantApplicationService.queryChannelInfoList(merchantAppDO.getSn(), merchantAppDO.getAppId(), payOrderDO.getProviderCode(),
                                    payOrderDO.getChannelCode(), null, null);
                            if (CollectionUtils.isEmpty(merchantAppChannelList)) {
                                return CommonResult.error(OpenApiResultCode.MERCHANT_APP_CHANNEL_NOT_EXIST);
                            }
                            CommonResult<MerchantAccessAuthDO> AtCommonResult = getSeqAtChannel(payOrderDO,payWayDO,merchantAppSubChannelDO,payWayDO.getType(),routerType,routerOrder,merchantAppChannelList);
                            if(AtCommonResult.isSuccess() && AtCommonResult.getData() != null){
                                // 关闭旧AT通道
                                MerchantAccessAuthDO updateMerchantAccessAuthDO = new MerchantAccessAuthDO();
                                updateMerchantAccessAuthDO.setState(0);
                                updateMerchantAccessAuthDO.setId(merchantAccessAuthDO.getId());
                                merchantAccessAuthService.updateMerchantAccessAuth(updateMerchantAccessAuthDO);
                                // 更新新AT通道
                                merchantAccessAuthDO = AtCommonResult.getData();
                                updateMerchantAccessAuthDO = new MerchantAccessAuthDO();
                                updateMerchantAccessAuthDO.setState(1);
                                updateMerchantAccessAuthDO.setId(merchantAccessAuthDO.getId());
                                merchantAccessAuthService.updateMerchantAccessAuth(updateMerchantAccessAuthDO);
                                if(merchantAccessAuthDO.getMerchantAppChannelDO() != null){
                                    // 关闭旧应用通道
                                    merchantApplicationService.updateMerchantAppChannelStatus(mchChannelCode,0,payOrderDO.getSn(),payOrderDO.getAppId());
                                    // 开启新应用通道
                                    merchantApplicationService.updateMerchantAppChannelStatus(merchantAccessAuthDO.getMerchantAppChannelDO().getCode(),1,payOrderDO.getSn(),payOrderDO.getAppId());
                                }
                            }else{
                                return CommonResult.error(0,AtCommonResult.getMsg());
                            }
                        }
                    }
                    break;
                case RANDOM_MULTIPLE:
                    log.info("merchantChannelRoute random go");

                    // 机构通道轮询
                    if(routerType == null ||  routerType == 0){
                        // 是否自动关闭
                        if(autoDealFailedNext != null && autoDealFailedNext ==  1){
                            merchantApplicationService.updateMerchantAppChannelStatus(mchChannelCode,0,payOrderDO.getSn(),payOrderDO.getAppId());
                            merchantApplicationService.updateMerchantAppChanneLimitRouter(mchChannelCode,0);
                        }
                    }else{
                        // 关闭AT 通道
                        if(autoDealFailedNext != null && autoDealFailedNext ==  1){
                            if(merchantAccessAuthNow != null){
                                MerchantAccessAuthDO updateMerchantAccessAuthDO = new MerchantAccessAuthDO();
                                updateMerchantAccessAuthDO.setState(0);
                                updateMerchantAccessAuthDO.setId(merchantAccessAuthNow.getId());
                                merchantAccessAuthService.updateMerchantAccessAuth(updateMerchantAccessAuthDO);
                            }
                        }
                    }
                    break;
            }
        }
        return CommonResult.success();
    }

    /**
     * 顺序机构轮询
     * @param sn
     * @param merchantAppChannelList  数据库应用通道集合
     * @param payWayCode
     * @param routerOrder
     * @return
     */
    private CommonResult<MerchantAppChannelDO> getSeqChannel(String mchChannelCode,String sn,List<MerchantAppChannelDO> merchantAppChannelList,String payWayCode,Integer routerOrder){
        // 通道编码顺序集合
        List<String> seqList = new ArrayList<>();
        for(MerchantAppChannelDO merchantAppChannelDO:merchantAppChannelList){
            seqList.add(merchantAppChannelDO.getCode());
        }
        log.info("merchantChannelRoute getSeqChannel seqList:{} ",JSONUtil.toJsonStr(seqList));
        // 位置
        int index = seqList.indexOf(mchChannelCode);
        log.info("merchantChannelRoute getSeqChannel start index:{},routerOrder:{} ",index,routerOrder);
        if(index == -1){
            log.error("merchantChannelRoute getSeqChannel 顺序单个机构轮询通道异常 当前通道不存在通道列表中sn:{} ",sn);
            return CommonResult.error(0,sn+":顺序单个机构轮询通道异常");
        }
        // 顺序
        if(routerOrder == 0){
            if(index == merchantAppChannelList.size() - 1){
                log.error("merchantChannelRoute getSeqChannel 顺序单个机构轮询通道异常,末尾无法继续向下轮询 sn:{} ",sn);
                return CommonResult.error(0,sn+":顺序单个机构轮询通道异常,末尾无法继续向下轮询");
            }
            index = index + 1;
        }else{
            if(index == 0){
                log.error("merchantChannelRoute getSeqChannel 顺序单个机构轮询通道异常,首位无法继续向上轮询 sn:{} ",sn);
                return CommonResult.error(0,sn+":顺序单个机构轮询通道异常,首位无法继续向上轮询");
            }
            index = index - 1;
        }
        log.info("merchantChannelRoute getSeqChannel start end:{} ",index);
        // index 区间判断
        if(index < 0 ||  index > merchantAppChannelList.size() - 1){
            log.error("merchantChannelRoute getSeqChannel 顺序单个机构轮询通道异常,轮询位置不在区间内 sn:{} ",sn);
            return CommonResult.error(0,sn+":顺序单个机构轮询通道异常,轮询位置不在区间内");
        }
        return CommonResult.success(merchantAppChannelList.get(index));
    }


    /**
     * 当AT通道不满足需要切换应用通道时，轮训所有应用通道
     * @param mchChannelCode
     * @param sn
     * @param merchantAppChannelList
     * @param payWayDO
     * @param routerOrder
     * @return
     */
    private CommonResult<MerchantAppChannelDO> getSeqAllChannel(String mchChannelCode,String sn,List<MerchantAppChannelDO> merchantAppChannelList,PayWayDO payWayDO,Integer routerOrder){
        // 通道编码顺序集合
        List<String> seqList = new ArrayList<>();
        // 通道编码 和  AT通道集合
        Map<String,List<MerchantAccessAuthDO>> authMap = new HashMap<>();
        MerchantAppChannelDO appChannelDO= null;
        List<MerchantAccessAuthDO> merchantAccessAuthList = null;
        for(MerchantAppChannelDO merchantAppChannelDO:merchantAppChannelList){
            // 查询所有AT通道
            merchantAccessAuthList = merchantAccessAuthService.routerAccessAuthList(merchantAppChannelDO.getAccessId(), PayEnums.PAY_TYPE.fromByCode(payWayDO.getType()),null,null);
            authMap.put(merchantAppChannelDO.getCode(),merchantAccessAuthList);
            seqList.add(merchantAppChannelDO.getCode());
        }
        // 获取索引位置
        int index = seqList.indexOf(mchChannelCode);
        log.info("merchantChannelRoute getSeqAllChannel start index:{},routerOrder:{} ",index,routerOrder);
        if(index < 0){
            log.error("merchantChannelRoute getSeqAllChannel 顺序单个机构轮询通道异常 当前通道不存在通道列表中,sn:{} ",sn);
            return CommonResult.error(0,sn+":顺序单个机构轮询通道异常");
        }

        // 顺序
        if(routerOrder == 0){
            if(index == merchantAppChannelList.size() - 1){
                log.error("merchantChannelRoute getSeqAllChannel 顺序单个机构轮询通道异常,末尾无法继续向下轮询 sn:{} ",sn);
                return CommonResult.error(0,sn+":顺序单个机构轮询通道异常,末尾无法继续向下轮询");
            }
            for(int i=index+1; i<merchantAppChannelList.size();i++){
                appChannelDO = merchantAppChannelList.get(i);
                if(ObjectUtil.isEmpty(authMap.get(appChannelDO.getCode()))){
                  continue;
                }
                log.info("merchantChannelRoute getSeqAllChannel start end:{} ",index);
                return CommonResult.success(appChannelDO);
            }
        }else{
            if(index == 0){
                log.error("merchantChannelRoute getSeqAllChannel 顺序单个机构轮询通道异常,首位无法继续向上轮询 sn:{} ",sn);
                return CommonResult.error(0,sn+":顺序单个机构轮询通道异常,首位无法继续向上轮询");
            }
            for(int i=index-1; i>=0;i--){
                appChannelDO = merchantAppChannelList.get(i);
                if(ObjectUtil.isEmpty(authMap.get(appChannelDO.getCode()))){
                    continue;
                }
                log.info("merchantChannelRoute getSeqAllChannel start end:{} ",index);
                return CommonResult.success(appChannelDO);
            }
        }
        return CommonResult.error(0,"getSeqAllChannel 顺序单个机构轮询通道异常，未匹配到数据");
    }

    /**
     * 顺序AT轮询
     * @param merchantAppSubChannelDO
     * @param type
     * @param limitRouter
     * @param routerOrder
     * @return
     */
    private CommonResult<MerchantAccessAuthDO> getSeqAtChannel(PayOrderDO payOrderDO,PayWayDO payWayDO,MerchantAppChannelDO merchantAppSubChannelDO,Integer type,Integer limitRouter,Integer routerOrder,List<MerchantAppChannelDO> merchantAppChannelList){
        String sn = payOrderDO.getSn();
        String mchChannelCode = payOrderDO.getMchChannelCode();
        if (merchantAppSubChannelDO != null && merchantAppSubChannelDO.getAccessId() != null) {
            // 是否切换下个应用宝通道
            MerchantAppChannelDO MerchantAppChannelNew = null;
            // 子通道路由
            if (PayEnums.PAY_TYPE.WECHAT.getCode().equals(type) || PayEnums.PAY_TYPE.ALIPAY.getCode().equals(type)) {
                PayEnums.PAY_TYPE payType = PayEnums.PAY_TYPE.fromByCode(type);
                // 查询AT通道
                List<MerchantAccessAuthDO> merchantAccessAuthList = merchantAccessAuthService.routerAccessAuthList(merchantAppSubChannelDO.getAccessId(), payType,null,null);
                if(CollUtil.isNotEmpty(merchantAccessAuthList)){
                    log.info("merchantChannelRoute getSeqAtChannel merchantAppChannelList:{}", JSONUtil.toJsonStr(merchantAccessAuthList));
                    String autCode = payOrderDO.getAutCode();
                    if(StrUtil.isEmpty(autCode)){
                        log.error("merchantChannelRoute getSeqAtChannel 顺序单个机构轮询AT通道异常 当前没有autCode, sn:{},payOrderNo:{} ",sn,payOrderDO.getPayOrderNo());
                        return CommonResult.error(0,sn+":顺序单个机构轮询AT通道异常");
                    }
                    // 通道编码顺序集合
                    List<String> seqList = new ArrayList<>();
                    for(MerchantAccessAuthDO merchantAccessAuthDO:merchantAccessAuthList){
                        seqList.add(merchantAccessAuthDO.getCode());
                    }
                    log.info("merchantChannelRoute getSeqAtChannel seqList:{} ",JSONUtil.toJsonStr(seqList));
                    // 位置
                    int index = seqList.indexOf(autCode);
                    log.info("merchantChannelRoute getSeqAtChannel start index:{},routerOrder:{} ",index,routerOrder);
                    if(index == -1){
                        log.error("merchantChannelRoute getSeqAtChannel 顺序单个机构轮询AT通道异常 当前通道不存在AT通道列表中,sn:{} ",sn);
                        return CommonResult.error(0,sn+":顺序单个机构轮询AT轮询通道异常");
                    }
                    // 顺序
                    if(routerOrder == 0){
                        if(index == merchantAccessAuthList.size() - 1){
                            log.error("merchantChannelRoute getSeqAtChannel 顺序单个机构轮询AT通道异常,末尾无法继续向下轮询,则轮询下个应用通道 sn:{} ",sn);
                            // 继续取下一个通道
                            CommonResult<MerchantAppChannelDO> merchantAppChannelDOCommonResult = getSeqAllChannel(mchChannelCode,sn,merchantAppChannelList,payWayDO,routerOrder);
                            if(merchantAppChannelDOCommonResult.isSuccess() && merchantAppChannelDOCommonResult.getData() != null){
                                MerchantAppChannelNew = merchantAppChannelDOCommonResult.getData();
                                CommonResult<MerchantAccessAuthDO> authDOCommonResult = getNextAtChannel(MerchantAppChannelNew,sn,payType.getCode());
                                if(authDOCommonResult.isSuccess() && authDOCommonResult.getData() != null) {
                                    authDOCommonResult.getData().setMerchantAppChannelDO(MerchantAppChannelNew);
                                }
                                return authDOCommonResult;
                            }else{
                                return CommonResult.error(0,merchantAppChannelDOCommonResult.getMsg());
                            }
                        }
                        index = index + 1;
                    }else{
                        if(index == 0){
                            // 继续取下一个通道
                            CommonResult<MerchantAppChannelDO> merchantAppChannelDOCommonResult = getSeqAllChannel(mchChannelCode,sn,merchantAppChannelList,payWayDO,routerOrder);
                            if(merchantAppChannelDOCommonResult.isSuccess() && merchantAppChannelDOCommonResult.getData() != null){
                                MerchantAppChannelNew = merchantAppChannelDOCommonResult.getData();
                                CommonResult<MerchantAccessAuthDO> authDOCommonResult = getNextAtChannel(MerchantAppChannelNew,sn,payType.getCode());
                                if(authDOCommonResult.isSuccess() && authDOCommonResult.getData() != null) {
                                    authDOCommonResult.getData().setMerchantAppChannelDO(MerchantAppChannelNew);
                                }
                                return authDOCommonResult;
                            }else{
                                return CommonResult.error(0,merchantAppChannelDOCommonResult.getMsg());
                            }
                        }
                        index = index - 1;
                    }
                    log.info("merchantChannelRoute getSeqAtChannel start end:{} ",index);
                    // index 区间判断
                    if(index < 0 ||  index > merchantAccessAuthList.size() - 1){
                        log.error("merchantChannelRoute getSeqAtChannel 顺序单个机构轮询AT通道异常,轮询位置不在区间内 sn:{} ",sn);
                        return CommonResult.error(0,sn+":顺序单个机构轮询AT通道异常,轮询位置不在区间内");
                    }
                    return CommonResult.success(merchantAccessAuthList.get(index));
                }
            }
        }
        return CommonResult.error(0,"getSeqAtChannel 顺序单个机构轮询通道异常，未匹配到数据");
    }

    /**
     * 切换下一个通道
     * @param merchantAppSubChannelDO
     * @param sn
     * @param type
     * @return
     */
    private CommonResult<MerchantAccessAuthDO> getNextAtChannel(MerchantAppChannelDO merchantAppSubChannelDO,String sn,Integer type){
        if (merchantAppSubChannelDO != null && merchantAppSubChannelDO.getAccessId() != null) {
            // 子通道路由
            if (PayEnums.PAY_TYPE.WECHAT.getCode().equals(type) || PayEnums.PAY_TYPE.ALIPAY.getCode().equals(type)) {
                PayEnums.PAY_TYPE payType = PayEnums.PAY_TYPE.fromByCode(type);
                // 查询AT通道
                List<MerchantAccessAuthDO> merchantAccessAuthList = merchantAccessAuthService.routerAccessAuthList(merchantAppSubChannelDO.getAccessId(), payType,null,null);
                if(CollUtil.isEmpty(merchantAccessAuthList)){
                    log.error("merchantChannelRoute getNextAtChannel 顺序单个机构轮询AT通道异常,切换通道查询AT通道列表为空 sn:{},mchChannelCode:{} ",sn,merchantAppSubChannelDO.getChannelCode());
                    return CommonResult.error(0,"切换通道查询AT通道列表为空");
                }
                // 获取已开启的AT通道列表
                List<MerchantAccessAuthDO> OpenAuthList = merchantAccessAuthList.stream().filter(merchantAccessAuthDO -> merchantAccessAuthDO.getState() != null && merchantAccessAuthDO.getState() == 1 ).collect(Collectors.toList());
                // 随机一个
                if(CollUtil.isNotEmpty(OpenAuthList)){
                    MerchantAccessAuthDO merchantAccessAuthDO = MerchantAppChannelRouterUtil.routerAt(OpenAuthList);
                    // 关闭其他AT通道状态
                    if(merchantAccessAuthDO != null){
                        for(MerchantAccessAuthDO authDO:OpenAuthList){
                            if(authDO.getId() != merchantAccessAuthDO.getId()){
                                MerchantAccessAuthDO updateMerchantAccessAuthDO = new MerchantAccessAuthDO();
                                updateMerchantAccessAuthDO.setState(0);
                                updateMerchantAccessAuthDO.setId(authDO.getId());
                                merchantAccessAuthService.updateMerchantAccessAuth(updateMerchantAccessAuthDO);
                            }
                        }
                    }
                    return CommonResult.success(merchantAccessAuthDO);
                }
                // 获取已关闭的AT通道列表
                List<MerchantAccessAuthDO> closeAuthList = merchantAccessAuthList.stream().filter(merchantAccessAuthDO -> merchantAccessAuthDO.getState() == null || merchantAccessAuthDO.getState() == 0 ).collect(Collectors.toList());
                if(CollUtil.isNotEmpty(closeAuthList)){
                    // 取第一个
                    MerchantAccessAuthDO merchantAccessAuthDO = closeAuthList.get(0);
                    // 开启状态
                    MerchantAccessAuthDO updateMerchantAccessAuthDO = new MerchantAccessAuthDO();
                    updateMerchantAccessAuthDO.setState(1);
                    updateMerchantAccessAuthDO.setId(merchantAccessAuthDO.getId());
                    merchantAccessAuthService.updateMerchantAccessAuth(updateMerchantAccessAuthDO);
                    return CommonResult.success(merchantAccessAuthDO);
                }
            }
        }
        return CommonResult.error(0,"无数据");
    }



    /**
     * 
     * @param routerPayList
     */
    public void processRouterMessage(List<RouterOrderMessageDto> routerPayList) {
        log.info("app路由处理 data:{}", JsonUtils.toJsonStringNotNull(routerPayList));
        Map<String, List<RouterOrderMessageDto>> appGroup = routerPayList.stream().collect(Collectors.groupingBy(routerPay -> routerPay.getAppId()));
        for (Map.Entry<String, List<RouterOrderMessageDto>> entry : appGroup.entrySet()) {
            log.info("app路由处理 appId:{}", entry.getKey());
            MerchantAppDO merchantAppDO = merchantApplicationService.queryDetailByAppId(entry.getKey());
            RouterConfigDto routerConfigDto = merchantAppDO.getRouterConfigDto();
            if (routerConfigDto == null) {
                log.info("路由配置为空 appId:{}", entry.getKey());
                continue;
            }
            if (CommonEnum.YES_NO_TYPE.NO.getCode().equals(routerConfigDto.getRouterType())) {
                log.info("当前app采用默认路由配置 appId:{}", entry.getKey());
                continue;
            }
            CommonEnum.YES_NO_TYPE yesNoType = CommonEnum.YES_NO_TYPE.from(routerConfigDto.getRouterStrategy());
            switch (yesNoType) {
                case NO:
                    processMchChannelRouter(merchantAppDO, routerConfigDto, entry.getValue());
                    break;
                case YES:
                    processAutRouter(merchantAppDO, routerConfigDto, entry.getValue());
                    break;
            }
        }
    }

    void processMchChannelRouter(MerchantAppDO merchantAppDO, RouterConfigDto routerConfigDto, List<RouterOrderMessageDto> routerPayList) {
        log.info("机构路由处理 appId:{}", merchantAppDO.getAppId());
        Map<String, List<RouterOrderMessageDto>> collect = routerPayList.stream().collect(Collectors.groupingBy(routerPay -> routerPay.getMchChannelCode()));
        LocalDateTime now = LocalDateTime.now();
        long currentTimeMillis = System.currentTimeMillis();
        collect.forEach((mchChannelCode, value) -> {
            boolean limitRouter = false;
            LimitRouterLogDO limitRouterLogDO = new LimitRouterLogDO();
            limitRouterLogDO.setRouterType(CommonEnum.YES_NO_TYPE.NO.getCode());
            limitRouterLogDO.setAppId(merchantAppDO.getAppId());
            if (CommonEnum.YES_NO_TYPE.YES.getCode().equals(routerConfigDto.getAutoDealFailedNext())) {
                // 首先判断是否交易失败
                List<RouterOrderMessageDto> failList = value.stream()
                        .filter(routerOrderMessageDto -> PayOrderEnums.PAY_ORDER_STATUS.FAIL.getCode().equals(routerOrderMessageDto.getState())).collect(Collectors.toList());
                if (!CollectionUtils.isEmpty(failList)) {
                    log.info("存在失败订单,进入流控 mchChannelCode:{}", mchChannelCode);
                    limitRouter = true;
                    limitRouterLogDO.setLimitType(1);
                }
            }
            // 是否存在成功率订单数据流控
            if (!limitRouter && routerConfigDto.getLimitMinutesSuccess() != null) {
                PayOrderQueryDto payOrderQueryDto = new PayOrderQueryDto();
                payOrderQueryDto.setMchChannelCode(mchChannelCode);
                payOrderQueryDto.setStartQueryTime(DateUtils.shanghaiDate(now.plusMinutes(-routerConfigDto.getLimitMinutesSuccess())));
                payOrderQueryDto.setEndQueryTime(currentTimeMillis);
                RouterOrderDataDto routerOrderDataDto = payOrderService.querySuccessOrder(payOrderQueryDto);
                BigDecimal decimal = MerchantUtils.divide(new BigDecimal(routerOrderDataDto.getSuccessOrder()), new BigDecimal(routerOrderDataDto.getEffectOrder()))
                        .multiply(new BigDecimal(100));
                if (decimal.compareTo(routerConfigDto.getLimitMinutesRateSuccess()) > 0) {
                    log.info("存在订单成功率,进入流控 mchChannelCode:{},limitMinutesSuccess:{},limitMinutesRateSuccess:{},routerOrderDataDto:{}", mchChannelCode,
                            routerConfigDto.getLimitMinutesSuccess(), routerConfigDto.getLimitMinutesRateSuccess(), JsonUtils.toJsonStringNotNull(routerOrderDataDto));
                    limitRouter = true;
                    limitRouterLogDO.setLimitType(3);
                    limitRouterLogDO.setLimitMinutes(routerConfigDto.getLimitMinutesSuccess());
                    limitRouterLogDO.setLimitValue(routerConfigDto.getLimitMinutesRateSuccess());
                    limitRouterLogDO.setValue(decimal);
                }

            }
            // 是否存在交易金额订单数据流控
            if (!limitRouter && routerConfigDto.getLimitOrderAmount() != null) {
                PayOrderQueryDto payOrderQueryDto = new PayOrderQueryDto();
                payOrderQueryDto.setMchChannelCode(mchChannelCode);
                payOrderQueryDto.setStartQueryTime(DateUtils.shanghaiDate(now.plusMinutes(-routerConfigDto.getLimitOrderMinutes())));
                payOrderQueryDto.setEndQueryTime(currentTimeMillis);
                payOrderQueryDto.setState(PayOrderEnums.PAY_ORDER_STATUS.SUCCESS.getCode());
                RouterOrderDataDto routerOrderDataDto = payOrderService.querySuccessOrderAmount(payOrderQueryDto);
                if (routerOrderDataDto.getSuccessOrderAmount().compareTo(routerConfigDto.getLimitOrderAmount()) > 0) {
                    log.info("存在订单金额,进入流控 mchChannelCode:{},limitMinutesSuccess:{},orderAmount:{},routerOrderDataDto:{}", mchChannelCode, routerConfigDto.getLimitOrderMinutes(),
                            routerConfigDto.getLimitOrderAmount(), JsonUtils.toJsonStringNotNull(routerOrderDataDto));
                    limitRouter = true;
                    limitRouterLogDO.setLimitType(4);
                    limitRouterLogDO.setLimitMinutes(routerConfigDto.getLimitOrderMinutes());
                    limitRouterLogDO.setLimitValue(routerConfigDto.getLimitOrderAmount());
                    limitRouterLogDO.setValue(routerOrderDataDto.getSuccessOrderAmount());
                }
            }
            if (!limitRouter) {
                return;
            }
            MerchantAppQueryDto merchantAppQueryDto = new MerchantAppQueryDto();
            merchantAppQueryDto.setAppId(merchantAppDO.getAppId());
            merchantAppQueryDto.setLimitRouter(CommonEnum.YES_NO_TYPE.YES.getCode());
            merchantAppQueryDto.setStatus(CommonEnum.YES_NO_TYPE.YES.getCode());
            merchantAppQueryDto.setPageNo(1);
            merchantAppQueryDto.setPageSize(1);
            MerchantAppChannelDO merchantAppChannelDO = merchantApplicationService.queryAppChannelDetail(mchChannelCode);
            // 0:顺序轮询
            if (CommonEnum.YES_NO_TYPE.NO.getCode().equals(routerConfigDto.getRouterOrder())) {
                merchantAppQueryDto.setMinId(merchantAppChannelDO.getId());
            }
            else {
                merchantAppQueryDto.setMaxId(merchantAppDO.getId());
            }
            merchantAppQueryDto.setPage(true);
            List<MerchantAppChannelDO> list = merchantApplicationService.queryChannelInfoList(merchantAppQueryDto);
            MerchantAppChannelDO effectMerchantAppDO = null;
            if (!CollectionUtils.isEmpty(list)) {
                effectMerchantAppDO = list.get(0);
            }
            // 原通道停用
            MerchantAppChannelDO updateMerchantAppChannelDO = new MerchantAppChannelDO();
            updateMerchantAppChannelDO.setId(merchantAppChannelDO.getId());
            updateMerchantAppChannelDO.setStatus(CommonEnum.YES_NO_TYPE.NO.getCode());
            merchantApplicationService.updateMerchantAppChannel(updateMerchantAppChannelDO, merchantAppChannelDO.getCode());
            limitRouterLogDO.setLimitCode(merchantAppChannelDO.getCode());
            if (routerConfigDto.getRouterStrategy() == 1) {
                if (effectMerchantAppDO != null) {
                    limitRouterLogDO.setNextCode(effectMerchantAppDO.getCode());
                }
                if (effectMerchantAppDO != null && CommonEnum.YES_NO_TYPE.NO.getCode().equals(effectMerchantAppDO.getStatus())) {
                    // 新通道启用
                    updateMerchantAppChannelDO = new MerchantAppChannelDO();
                    updateMerchantAppChannelDO.setId(effectMerchantAppDO.getId());
                    updateMerchantAppChannelDO.setStatus(CommonEnum.YES_NO_TYPE.YES.getCode());
                    merchantApplicationService.updateMerchantAppChannel(updateMerchantAppChannelDO, effectMerchantAppDO.getCode());
                }
            }
            businessLogService.addLimitRouterLog(limitRouterLogDO);
        });
    }

    void processAutRouter(MerchantAppDO merchantAppDO, RouterConfigDto routerConfigDto, List<RouterOrderMessageDto> routerPayList) {
        log.info("AUT路由处理 appId:{}", merchantAppDO.getAppId());
        Map<String, List<RouterOrderMessageDto>> collect = routerPayList.stream().filter(routerPay -> StringUtils.hasText(routerPay.getAutCode()))
                .collect(Collectors.groupingBy(routerPay -> routerPay.getAutCode()));
        LocalDateTime now = LocalDateTime.now();
        long currentTimeMillis = System.currentTimeMillis();
        collect.forEach((autCode, value) -> {
            boolean limitRouter = false;
            LimitRouterLogDO limitRouterLogDO = new LimitRouterLogDO();
            limitRouterLogDO.setAppId(merchantAppDO.getAppId());
            limitRouterLogDO.setRouterType(CommonEnum.YES_NO_TYPE.YES.getCode());
            if (CommonEnum.YES_NO_TYPE.YES.getCode().equals(routerConfigDto.getAutoDealFailedNext())) {
                // 首先判断是否交易失败
                List<RouterOrderMessageDto> failList = value.stream()
                        .filter(routerOrderMessageDto -> PayOrderEnums.PAY_ORDER_STATUS.FAIL.getCode().equals(routerOrderMessageDto.getState())).collect(Collectors.toList());
                if (!CollectionUtils.isEmpty(failList)) {
                    log.info("存在失败订单,进入流控 autCode:{}", autCode);
                    limitRouter = true;
                    limitRouterLogDO.setLimitType(1);
                }
            }
            // 是否存在成功率订单数据流控
            if (!limitRouter && routerConfigDto.getLimitMinutesSuccess() != null) {
                PayOrderQueryDto payOrderQueryDto = new PayOrderQueryDto();
                payOrderQueryDto.setAutCode(autCode);
                payOrderQueryDto.setStartQueryTime(DateUtils.shanghaiDate(now.plusMinutes(-routerConfigDto.getLimitMinutesSuccess())));
                payOrderQueryDto.setEndQueryTime(currentTimeMillis);
                RouterOrderDataDto routerOrderDataDto = payOrderService.querySuccessOrder(payOrderQueryDto);
                BigDecimal decimal = MerchantUtils.divide(new BigDecimal(routerOrderDataDto.getSuccessOrder()), new BigDecimal(routerOrderDataDto.getEffectOrder()))
                        .multiply(new BigDecimal(100));
                if (decimal.compareTo(routerConfigDto.getLimitMinutesRateSuccess()) > 0) {
                    log.info("存在订单成功率,进入流控 autCode:{},limitMinutesSuccess:{},limitMinutesRateSuccess:{},routerOrderDataDto:{}", autCode, routerConfigDto.getLimitMinutesSuccess(),
                            routerConfigDto.getLimitMinutesRateSuccess(), JsonUtils.toJsonStringNotNull(routerOrderDataDto));
                    limitRouter = true;
                    limitRouterLogDO.setLimitType(3);
                    limitRouterLogDO.setLimitMinutes(routerConfigDto.getLimitMinutesSuccess());
                    limitRouterLogDO.setLimitValue(routerConfigDto.getLimitMinutesRateSuccess());
                    limitRouterLogDO.setValue(decimal);
                }

            }
            // 是否存在交易金额订单数据流控
            if (!limitRouter && routerConfigDto.getLimitOrderAmount() != null) {
                PayOrderQueryDto payOrderQueryDto = new PayOrderQueryDto();
                payOrderQueryDto.setAutCode(autCode);
                payOrderQueryDto.setStartQueryTime(DateUtils.shanghaiDate(now.plusMinutes(-routerConfigDto.getLimitOrderMinutes())));
                payOrderQueryDto.setEndQueryTime(currentTimeMillis);
                payOrderQueryDto.setState(PayOrderEnums.PAY_ORDER_STATUS.SUCCESS.getCode());
                RouterOrderDataDto routerOrderDataDto = payOrderService.querySuccessOrderAmount(payOrderQueryDto);
                if (routerOrderDataDto.getSuccessOrderAmount().compareTo(routerConfigDto.getLimitOrderAmount()) > 0) {
                    log.info("存在订单金额,进入流控 autCode:{},limitMinutesSuccess:{},orderAmount:{},routerOrderDataDto:{}", autCode, routerConfigDto.getLimitOrderMinutes(),
                            routerConfigDto.getLimitOrderAmount(), JsonUtils.toJsonStringNotNull(routerOrderDataDto));
                    limitRouter = true;
                    limitRouterLogDO.setLimitType(4);
                    limitRouterLogDO.setLimitMinutes(routerConfigDto.getLimitOrderMinutes());
                    limitRouterLogDO.setLimitValue(routerConfigDto.getLimitOrderAmount());
                    limitRouterLogDO.setValue(routerOrderDataDto.getSuccessOrderAmount());
                }
            }
            if (!limitRouter) {
                return;
            }
            MerchantAccessAuthDO merchantAccessAuthDO = merchantAccessAuthService.queryMerchantAccessAuthByCode(autCode);
            MerchantAccessAuthQueryDto accessAuthQueryDto = new MerchantAccessAuthQueryDto();
            accessAuthQueryDto.setAccessId(merchantAccessAuthDO.getAccessId());
            accessAuthQueryDto.setLimitRouter(CommonEnum.YES_NO_TYPE.YES.getCode());
            accessAuthQueryDto.setState(CommonEnum.YES_NO_TYPE.YES.getCode());
            accessAuthQueryDto.setPageNo(1);
            accessAuthQueryDto.setPageSize(1);
            // 0:顺序轮询
            if (CommonEnum.YES_NO_TYPE.NO.getCode().equals(routerConfigDto.getRouterOrder())) {
                accessAuthQueryDto.setMinId(merchantAccessAuthDO.getId());
            }
            else {
                accessAuthQueryDto.setMaxId(merchantAccessAuthDO.getId());
            }
            PageResult<MerchantAccessAuthDO> doPageResult = merchantAccessAuthService.queryAuthPage(accessAuthQueryDto);
            List<MerchantAccessAuthDO> list = doPageResult.getList();

            MerchantAccessAuthDO effectMerchantAccessAuth = null;
            if (!CollectionUtils.isEmpty(list)) {
                effectMerchantAccessAuth = list.get(0);
            }
            // 原通道停用
            MerchantAccessAuthDO updateMerchantAccessAuth = new MerchantAccessAuthDO();
            updateMerchantAccessAuth.setId(merchantAccessAuthDO.getId());
            updateMerchantAccessAuth.setState(CommonEnum.YES_NO_TYPE.NO.getCode());
            merchantAccessAuthService.updateMerchantAccessAuth(updateMerchantAccessAuth);
            limitRouterLogDO.setLimitCode(merchantAccessAuthDO.getCode());
            if (effectMerchantAccessAuth != null) {
                limitRouterLogDO.setNextCode(effectMerchantAccessAuth.getCode());
            }
            if (effectMerchantAccessAuth != null) {
                if (CommonEnum.YES_NO_TYPE.NO.getCode().equals(effectMerchantAccessAuth.getState())) {
                    // 新通道启用
                    updateMerchantAccessAuth = new MerchantAccessAuthDO();
                    updateMerchantAccessAuth.setId(effectMerchantAccessAuth.getId());
                    updateMerchantAccessAuth.setState(CommonEnum.YES_NO_TYPE.YES.getCode());
                    merchantAccessAuthService.updateMerchantAccessAuth(updateMerchantAccessAuth);
                }
            }
            else {
                // 关闭主通道
                MerchantAppChannelDO merchantAppChannelDO = merchantApplicationService.queryDetailByAccessId(merchantAccessAuthDO.getAccessId(),
                        MerchantEnum.DATA_RELATION_TYPE.ACCESS);
                if (merchantAppChannelDO != null) {
                    if (CommonEnum.YES_NO_TYPE.YES.getCode().equals(merchantAppChannelDO.getLimitRouter())) {
                        // 关闭当前通道 打开下一个通道
                        MerchantAppChannelDO updateMerchantAppDO = new MerchantAppChannelDO();
                        updateMerchantAppDO.setId(merchantAppChannelDO.getId());
                        updateMerchantAppDO.setStatus(CommonEnum.YES_NO_TYPE.NO.getCode());
                        merchantApplicationService.updateMerchantAppChannel(updateMerchantAppDO, merchantAppChannelDO.getCode());
                        limitRouterLogDO.setLimitChannel(CommonEnum.YES_NO_TYPE.YES.getCode());
                        if (routerConfigDto.getRouterStrategy() == 1) {
                            MerchantAppQueryDto merchantAppQueryDto = new MerchantAppQueryDto();
                            merchantAppQueryDto.setAppId(merchantAppDO.getAppId());
                            merchantAppQueryDto.setLimitRouter(CommonEnum.YES_NO_TYPE.YES.getCode());
                            merchantAppQueryDto.setStatus(CommonEnum.YES_NO_TYPE.YES.getCode());
                            merchantAppQueryDto.setPageNo(1);
                            merchantAppQueryDto.setPageSize(1);
                            // 0:顺序轮询
                            if (CommonEnum.YES_NO_TYPE.NO.getCode().equals(routerConfigDto.getRouterOrder())) {
                                merchantAppQueryDto.setMinId(merchantAppChannelDO.getId());
                            }
                            else {
                                merchantAppQueryDto.setMaxId(merchantAppDO.getId());
                            }
                            merchantAppQueryDto.setPage(true);
                            List<MerchantAppChannelDO> merchantAppChannels = merchantApplicationService.queryChannelInfoList(merchantAppQueryDto);
                            MerchantAppChannelDO effectMerchantAppDO = null;
                            if (!CollectionUtils.isEmpty(list)) {
                                effectMerchantAppDO = merchantAppChannels.get(0);
                                if (effectMerchantAppDO != null && CommonEnum.YES_NO_TYPE.NO.getCode().equals(effectMerchantAppDO.getStatus())) {
                                    // 新通道启用
                                    MerchantAppChannelDO updateMerchantAppChannelDO = new MerchantAppChannelDO();
                                    updateMerchantAppChannelDO.setId(effectMerchantAppDO.getId());
                                    updateMerchantAppChannelDO.setStatus(CommonEnum.YES_NO_TYPE.YES.getCode());
                                    merchantApplicationService.updateMerchantAppChannel(updateMerchantAppChannelDO, effectMerchantAppDO.getCode());
                                }
                            }
                        }
                    }
                }
            }
            businessLogService.addLimitRouterLog(limitRouterLogDO);
        });
    }

    public static void main(String[] args) {

        List<String> list = new ArrayList<>();
        list.add("1");
        list.add("2");
        list.add("3");
        list.add("4");
        list.add("5");
        list.add("6");
        list.add("7");
        list.add("8");

        String value = "8";
        int index = list.indexOf(value);

        System.out.println("顺序");
        for(int i=index+1; i<list.size();i++){
            System.out.println(i+"-"+list.get(i));
        }
        System.out.println("倒序");
        for(int i=index-1; i>=0;i--){
            System.out.println(i+"-"+list.get(i));
        }
    }

}
